//+------------------------------------------------------------------+
//|                                                      TripleMA.mq5 |
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                             https://www.mmeta.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Software Corp."
#property link      "https://www.mmeta.com"
#property version   "1.00"

//--- 输入参数
input int      InpFastMAPeriod = 1;     // 快速MA周期
input int      InpMediumMAPeriod = 3;  // 中速MA周期
input int      InpSlowMAPeriod = 5;    // 慢速MA周期
input double   InpLotSize = 0.1;        // 交易手数
input int      InpTrailingStop = 50;    // 移动止损点数
input int      InpMagicNumber = 12345;  // EA魔术码
input int      setTime = 0.5;

//--- 全局变量
int    fastMA, mediumMA, slowMA;
double prevFast, prevMedium, prevSlow;
double highestHigh, lowestLow;
ENUM_ORDER_TYPE_FILLING  MyFILLING;

bool openSignal = true;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   // 创建MA指标句柄
   fastMA = iMA(_Symbol, _Period, InpFastMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
   mediumMA = iMA(_Symbol, _Period, InpMediumMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
   slowMA = iMA(_Symbol, _Period, InpSlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
   
   if(fastMA == INVALID_HANDLE || mediumMA == INVALID_HANDLE || slowMA == INVALID_HANDLE)
   {
      Print("指标初始化失败");
      return(INIT_FAILED);
   }
   
   // 初始化前值
   prevFast = 0;
   prevMedium = 0;
   prevSlow = 0;

   EventSetTimer(1); // 每 50 秒触发一次 OnTimer()
   
   return(INIT_SUCCEEDED);
}


// 定时器事件回调
void OnTimer() {
   openSignal = false;
   Print("定时器触发：每 50 秒执行一次");
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   IndicatorRelease(fastMA);
   IndicatorRelease(mediumMA);
   IndicatorRelease(slowMA);
   EventKillTimer();
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+

void OnTick()
{
   // 获取当前MA值
   SetSymbolFillMode(Symbol()); //设定该品种Fillingmode
   double fast[2], medium[2], slow[2];
   CopyBuffer(fastMA, 0, 0, 2, fast);
   CopyBuffer(mediumMA, 0, 0, 2, medium);
   CopyBuffer(slowMA, 0, 0, 2, slow);
   
   // 检查是否有新交叉信号
   bool buySignal = false;
   bool sellSignal = false;
   
   // 三均线金叉：快线同时上穿中线和慢线
   if(fast[1] > medium[1] && fast[1] > slow[1] &&
      prevFast <= prevMedium && prevFast <= prevSlow && slow[1]-medium[1]-fast[1])
   {
      buySignal = true;
   }
   
   // 三均线死叉：快线同时下穿中线和慢线
   if(fast[1] < medium[1] && fast[1] < slow[1] &&
      prevFast >= prevMedium && prevFast >= prevSlow&&slow[1]-medium[1]-fast[1])
   {
      sellSignal = true;
   }
   
   // 更新前值
   prevFast = fast[1];
   prevMedium = medium[1];
   prevSlow = slow[1];
   
   // 检查持仓
   bool positionExists = false;
   if(PositionSelect(_Symbol))
   {
      positionExists = true;
      ManageTrailingStop(); // 管理移动止损
   }
   
   // 执行交易逻辑
   if(!positionExists)
   {
      if(buySignal)
      {
          OpenTrade(ORDER_TYPE_BUY);
          openSignal = true;
      }
      else if(sellSignal)
      {
         OpenTrade(ORDER_TYPE_SELL);
      }
   }
}
void SetSymbolFillMode(string Symbol_x)
  {
   MyFILLING=ORDER_FILLING_RETURN;
   int FILLING=(int)SymbolInfoInteger(Symbol_x,SYMBOL_FILLING_MODE);
   if((FILLING&SYMBOL_FILLING_IOC)==SYMBOL_FILLING_IOC)
      MyFILLING=ORDER_FILLING_IOC;
   if((FILLING&SYMBOL_FILLING_FOK)==SYMBOL_FILLING_FOK)
      MyFILLING=ORDER_FILLING_FOK;
  }

//+------------------------------------------------------------------+
//| 开仓函数                                                         |
//+------------------------------------------------------------------+
void OpenTrade(ENUM_ORDER_TYPE orderType)
{
   MqlTradeRequest request = {};
   MqlTradeResult  result = {};
   
   request.action = TRADE_ACTION_DEAL;
   request.symbol = _Symbol;
   request.volume = InpLotSize;
   request.type = orderType;
   request.price = SymbolInfoDouble(_Symbol, orderType==ORDER_TYPE_BUY ? SYMBOL_ASK : SYMBOL_BID);
   request.deviation = 5;
   request.magic = InpMagicNumber;
    request.type_filling = MyFILLING;
   
   // 发送交易请求
   if(!OrderSend(request, result))
   {
      Print("开仓失败，错误代码：", GetLastError());
   }
   else 
   {
      // 初始化跟踪止损基准
      if(orderType == ORDER_TYPE_BUY)
         highestHigh = result.price;
      else
         lowestLow = result.price;
   }
}

//+------------------------------------------------------------------+
//| 管理移动止损函数                                                 |
//+------------------------------------------------------------------+
void ManageTrailingStop()
{
   ulong posTicket = PositionGetTicket(0);
   if(posTicket <= 0) return;
   
   double currentStopLoss = PositionGetDouble(POSITION_SL);
   double newStopLoss = currentStopLoss;
   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   
   if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
   {
      highestHigh = MathMax(highestHigh, SymbolInfoDouble(_Symbol, SYMBOL_BID));
      newStopLoss = highestHigh - InpTrailingStop * point;
      newStopLoss = NormalizeDouble(newStopLoss, _Digits);
      
      if(newStopLoss > currentStopLoss)
      {
         ModifyStopLoss(posTicket, newStopLoss);
      }
   }
   else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
   {
      lowestLow = MathMin(lowestLow, SymbolInfoDouble(_Symbol, SYMBOL_ASK));
      newStopLoss = lowestLow + InpTrailingStop * point;
      newStopLoss = NormalizeDouble(newStopLoss, _Digits);
      
      if(newStopLoss < currentStopLoss || currentStopLoss == 0)
      {
         ModifyStopLoss(posTicket, newStopLoss);
      }
   }
}

//+------------------------------------------------------------------+
//| 修改止损函数                                                     |
//+------------------------------------------------------------------+
void ModifyStopLoss(ulong ticket, double sl)
{
   MqlTradeRequest request = {};
   MqlTradeResult result = {};
   
   request.action = TRADE_ACTION_SLTP;
   request.position = ticket;
   request.symbol = _Symbol;
   request.sl = sl;
   request.magic = InpMagicNumber;
   
   if(!OrderSend(request, result))
   {
      Print("修改止损失败，错误代码：", GetLastError());
   }
}
//+------------------------------------------------------------------+